package csv_rows

import (
    "encoding/csv"
    "errors"
    "fmt"
    "io"
    "os"
    "path/filepath"
    "reflect"
    "strconv"
    "time"

    "github.com/jszwec/csvutil"
    "libgo/utils"
)

func LoadFromReader(r io.Reader, rows interface{}) error {

    typ := reflect.TypeOf(rows)
    val := reflect.ValueOf(rows)
    if val.Kind() != reflect.Ptr {
        return errors.New("not a pointer")
    }
    if typ.Elem().Kind() != reflect.Slice {
        return errors.New("not a slice")
    }

    cr := csv.NewReader(r)
    dec, err := csvutil.NewDecoder(cr)
    if err != nil {
        return err
    }
    dec.Map = func(field, col string, v interface{}) string {

        switch v.(type) {
        case time.Duration:
            d, err := time.ParseDuration(field)
            if err != nil {
                return field
            }
            return fmt.Sprint(int64(d))
        case int, int8, int16, int32, int64:
            d, err := strconv.ParseInt(field, 0, 64)
            if err != nil {
                return field
            }
            return fmt.Sprint(d)
        case uint, uint8, uint16, uint32, uint64:
            d, err := strconv.ParseUint(field, 0, 64)
            if err != nil {
                return field
            }
            return fmt.Sprint(d)
        }
        return field
    }

    for {
        obj := reflect.New(typ.Elem().Elem())
        err := dec.Decode(obj.Interface())
        if err == io.EOF {
            break
        }
        if err != nil {
            return err
        }
        val.Elem().Set(reflect.Append(val.Elem(), obj.Elem()))
    }
    return nil
}

func LoadFromFile(fname string, rows interface{}) error {
    var fpath = fname
    if !filepath.IsAbs(fpath) {
        fpath = filepath.Join(utils.ProjectRoot(), fname)
    }
    fpath = filepath.Clean(fpath)
    fp, err := os.OpenFile(fpath, os.O_RDONLY, 0666)
    if err != nil {
        return err
    }
    defer fp.Close()

    return LoadFromReader(fp, rows)
}
